﻿using UnityEditor;
using UnityEngine;
using System;

namespace GameBasic.Editors
{
    [CustomPropertyDrawer(typeof(BitsMaskAttribute))]
    public class BitsMaskAttributeDrawer : PropertyDrawer
    {
        // TODO: 可配置
        const int GridRowCount = 4;
        const int GridColumnCount = 8;

        const int GridCellWidh = 20;
        const int GridCellHeight = 20;
        const int LineHeight = 20;
        // Button Text
        const string Text_Left = "←";
        const string Text_Right = "→";
        const string Text_Up = "↑";
        const string Text_Down = "↓";
        // 
        const string Text_All = "A";
        const string Text_Clear = "C";
        const string Text_Revert = "R";

        bool editing;

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            BitsMaskAttribute maskAttribute = attribute as BitsMaskAttribute;

            // 一行属性，一行格子标签
            // 一行移位按钮
            // 一行 “复位”“全选” 按钮
            // 一行留白
            if (editing)
                return LineHeight * (GridRowCount + 5);
            return LineHeight;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            BitsMaskAttribute maskAttribute = attribute as BitsMaskAttribute;

            DrawBaseElement(position, property.displayName, property);
            if (editing)
            {
                DrawMaskGrid(position, property);
                DrawButtons(position, property);
            }
        }

        void DrawBaseElement(Rect position, string displayName, SerializedProperty property)
        {
            Rect valueFieldRect = new Rect(position.x, position.y, position.width - 20, LineHeight);
            Rect showGridToggleRect = new Rect(position.width + 5, position.y, 20, LineHeight);

            property.longValue = (uint)EditorGUI.LongField(valueFieldRect, displayName, (uint)property.longValue);
            editing = EditorGUI.Toggle(showGridToggleRect, editing);
        }

        void DrawMaskGrid(Rect position, SerializedProperty property)
        {
            int toggleIndex;
            uint toggleValue;
            float gridPosX;
            float gridPosY;
            Vector2 gridPos;
            Vector2 gridSize = new Vector2(GridCellWidh, GridCellHeight);

            for (int i = 0; i < GridRowCount; i++)
            {
                for (int j = 0; j < GridColumnCount; j++)
                {
                    toggleIndex = i * GridColumnCount + j;
                    toggleValue = 1u << toggleIndex;
                    gridPosX = position.width - GridCellWidh * (GridColumnCount - j - 1);
                    gridPosY = position.y + LineHeight * (i + 1) + 5;
                    gridPos = new Vector2(gridPosX, gridPosY);

                    // 绘制格子
                    if (EditorGUI.Toggle(new Rect(gridPos, gridSize), (property.longValue & toggleValue) != 0))
                        property.longValue |= toggleValue;
                    else
                        property.longValue &= ~toggleValue;
                }
            }
        }

        void DrawButtons(Rect position, SerializedProperty property)
        {
            ulong longValue = (ulong)property.longValue;

            float intFieldWidth = position.width * 0.5f;
            float moveBitBtnWidth = LineHeight;
            float bitLinePosY = position.y + LineHeight * (GridRowCount + 3);
            float btnLinePosY = bitLinePosY + LineHeight;
            Vector2 intFieldPos = new Vector2(position.x, bitLinePosY);
            Vector2 intFieldSize = new Vector2(intFieldWidth, LineHeight);
            Vector2 moveLeftBtnPos = intFieldPos + Vector2.right * intFieldWidth;
            Vector2 moveBitBtnSize = new Vector2(moveBitBtnWidth, LineHeight);

            // Move btn
            Rect btnRect = new Rect(moveLeftBtnPos, moveBitBtnSize);
            Vector2 right = Vector2.right * moveBitBtnWidth;

            if (GUI.Button(btnRect, Text_Left))
                longValue >>= 1;
            if (GUI.Button(btnRect.Translate(right), Text_Right))
                longValue <<= 1;
            if (GUI.Button(btnRect.Translate(right), Text_Up))
                longValue >>= GridColumnCount;
            if (GUI.Button(btnRect.Translate(right), Text_Down))
                longValue <<= GridColumnCount;

            // TODO: Tooltips
            // All, Clear, Revert
            if (GUI.Button(btnRect.Translate(right * 2), Text_All))
                longValue = ulong.MaxValue;
            if (GUI.Button(btnRect.Translate(right), Text_Clear))
                longValue = 0u;
            if (GUI.Button(btnRect.Translate(right), Text_Revert))
                longValue = ~longValue;

            property.longValue = (uint)longValue;
        }
    }
}